package com.gitee.jmash.rbac.utils;

import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.gitee.jmash.rbac.RbacFactory;
import com.gitee.jmash.rbac.entity.OpenAppEntity;
import com.gitee.jmash.rbac.mapper.OpenAppMapper;
import com.gitee.jmash.rbac.model.UserOpenCreateReq;
import com.gitee.jmash.rbac.service.OpenAppRead;
import com.google.protobuf.BoolValue;
import com.xyvcard.wechat.client.WechatClient;
import com.xyvcard.weixin.auth.service.DirectMiniAppService;
import com.xyvcard.weixin.wechat.model.MiniLoginResp;
import com.xyvcard.weixin.wechat.model.PhoneInfo;
import com.xyvcard.weixin.wechat.model.PhoneNumberResp;
import jakarta.enterprise.inject.spi.CDI;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jmash.rbac.protobuf.GzhSubscribeCheckReq;
import jmash.rbac.protobuf.MiniAppLoginReq;
import jmash.rbac.protobuf.MiniAppPhoneNumberReq;
import jmash.rbac.protobuf.OpensType;
import xyvcard.wechat.protobuf.MiniAppPhoneReq;
import xyvcard.wechat.protobuf.MiniAppPhoneResp;
import xyvcard.wechat.protobuf.MiniAppUserOpenIdReq;
import xyvcard.wechat.protobuf.MiniAppUserOpenIdResp;
import xyvcard.wechat.protobuf.SubscribeCheckReq;

/**
 * 小程序工具类.
 */
public class MiniappUtil {

  private static Log log = LogFactory.getLog(MiniappUtil.class);

  // 本地配置App
  public static DirectMiniAppService getDirectMiniAppService() {
    return CDI.current().select(DirectMiniAppService.class).get();
  }

  protected static MiniLoginResp findMiniAppUserOpenId(MiniAppLoginReq req) {
    MiniAppUserOpenIdReq.Builder builder = MiniAppUserOpenIdReq.newBuilder();
    builder.setTenant(req.getTenant()).setComponentAppid(req.getComponentAppid())
        .setAuthorizerAppid(req.getAppId()).setLoginCode(req.getLoginCode());
    MiniAppUserOpenIdResp resp =
        WechatClient.getWechatBlockingStub().findMiniAppUserOpenId(builder.build());
    return OpenAppMapper.INSTANCE.userOpenId(resp);
  }

  protected static PhoneInfo findMiniAppPhoneNumber(MiniAppPhoneNumberReq req) {
    MiniAppPhoneReq.Builder builder = MiniAppPhoneReq.newBuilder();
    builder.setTenant(req.getTenant()).setComponentAppid(req.getComponentAppid())
        .setAuthorizerAppid(req.getAppId()).setPhoneCode(req.getPhoneCode());
    MiniAppPhoneResp resp =
        WechatClient.getWechatBlockingStub().findMiniAppPhoneNumber(builder.build());
    return OpenAppMapper.INSTANCE.userPhoneNumber(resp);
  }

  // 获取小程序登录OpenId信息.
  public static MiniLoginResp getUserOpenId(@NotNull @Valid MiniAppLoginReq req) {
    if (StringUtils.isNotBlank(req.getComponentAppid())) {
      MiniLoginResp resp = findMiniAppUserOpenId(req);
      return resp;
    }
    try (OpenAppRead openAppRead = RbacFactory.getOpenAppRead(req.getTenant())) {
      // 本地配置appId.
      OpenAppEntity appEntity = openAppRead.findByAppId(req.getAppId());
      if (appEntity != null) {
        MiniLoginResp resp = getDirectMiniAppService().login(req.getAppId(),
            appEntity.getAppSecret(), req.getLoginCode());
        return resp;
      } else {
        throw new RuntimeException("未配置APP密钥信息.");
      }
    } catch (Exception ex) {
      log.error("", ex);
      throw new RuntimeException(ex);
    }
  }

  // 获取小程序登录手机号信息.
  public static PhoneInfo getPhoneNumber(@NotNull @Valid MiniAppPhoneNumberReq req) {
    if (StringUtils.isNotBlank(req.getComponentAppid())) {
      PhoneInfo resp = findMiniAppPhoneNumber(req);
      return resp;
    }
    try (OpenAppRead openAppRead = RbacFactory.getOpenAppRead(req.getTenant())) {
      // 本地配置appId.
      OpenAppEntity appEntity = openAppRead.findByAppId(req.getAppId());
      if (appEntity != null) {
        PhoneNumberResp resp = getDirectMiniAppService().phoneNumber(req.getAppId(),
            appEntity.getAppSecret(), req.getPhoneCode());
        return resp.getPhoneInfo();
      } else {
        throw new RuntimeException("未配置APP密钥信息.");
      }
    } catch (Exception ex) {
      log.error("", ex);
      throw new RuntimeException(ex);
    }
  }

  // 获取用户登录信息.
  public static MiniLoginResp getMiniLoginResp(@NotNull @Valid MiniAppPhoneNumberReq req) {
    MiniAppLoginReq request =
        MiniAppLoginReq.newBuilder().setTenant(req.getTenant()).setLoginCode(req.getLoginCode())
            .setAppId(req.getAppId()).setComponentAppid(req.getComponentAppid()).build();
    return getUserOpenId(request);
  }

  // 获取用户注册绑定登录信息.
  public static UserOpenCreateReq getCreateUserInfo(@NotNull @Valid MiniAppPhoneNumberReq req,PhoneInfo phoneResp,
      @NotNull MiniLoginResp openIdResp) {
    UserOpenCreateReq user = new UserOpenCreateReq();
    user.setOpenType(OpensType.wechat);
    user.setAppid(req.getAppId());
    user.setNickName(req.getNickName());
    user.setTenant(req.getTenant());
    user.setOpenid(openIdResp.getOpenid());
    user.setUnionid(openIdResp.getUnionid());
    user.setMobilePhone(phoneResp.getPurePhoneNumber());
    user.setCountryCode(phoneResp.getCountryCode());
    return user;
  }

  // 判断用户union_id是否关注某公众号.
  public static boolean checkSubscribe(@NotNull @Valid GzhSubscribeCheckReq req,
      List<String> unionIds) {

    if (unionIds.isEmpty()) {
      return false;
    }
    for (String unionId : unionIds) {
      if (StringUtils.isBlank(unionId)) {
        continue;
      }
      SubscribeCheckReq request = SubscribeCheckReq.newBuilder().setTenant(req.getTenant())
          .setAppId(req.getAppId())
          .setUnionId(unionId).build();
      BoolValue value = WechatClient.getWechatBlockingStub().checkSubscribe(request);
      if (value.getValue()) {
        return true;
      }
    }
    return false;
  }

}
